package com.onstar.cn.map;

import java.util.List;

import android.location.Address;
import android.view.View;
import android.widget.LinearLayout;

import com.amap.api.maps2d.AMap;
import com.amap.api.services.core.LatLonPoint;
import com.onstar.cn.map.common.DriveMode;
import com.onstar.cn.map.common.DriveSegmentInfo;
import com.onstar.cn.map.common.Language;
import com.onstar.cn.map.common.LocationType;
import com.onstar.cn.map.common.PoiItemInfo;
import com.onstar.cn.map.common.PoiType;
import com.onstar.cn.map.core.OGeoPoint;
import com.onstar.cn.map.listener.AMapLongPressHandler;
import com.onstar.cn.map.listener.OMapLongPressListener;
import com.onstar.cn.map.listener.ORouteHandlerListener;
import com.onstar.cn.map.listener.OSearchHandlerListener;
import com.onstar.cn.map.util.BackgroundThread;
import com.onstar.cn.map.util.MapViewHelper;
import com.onstar.cn.map.util.QueryOptions;

/**
 * Refactor the mess class of MapHandler here.
 * 
 * @author Qiying Gong
 * 
 * @Created 2013-4-12
 */
public class MapContainerImpl implements MapContainer {
	private MapViewHelper mapViewHelper;

	private OMapActivity mMapActivity;

	private AMap mMapView;

	private MapRoute oroute;
	private MapLocation mapLocation;
	private MapSearch mapSearch;

	private Address mVehicleAddress;
	private Language language = Language.ZH_CN;
	private QueryOptions queryOptions;

	/**
	 * Get Query options from map container implementation.
	 * 
	 * @return the queryOptions
	 */
	@Override
	public QueryOptions getQueryOptions() {
		return queryOptions;
	}

	/**
	 * Update query options from outside of map container
	 * 
	 * @param queryOptions
	 *            the queryOptions to set
	 */
	@Override
	public void setQueryOptions(QueryOptions queryOptions) {
		this.queryOptions = queryOptions;
	}

	public Address getMVehicleAddress() {
		return mVehicleAddress;
	}

	public void setMVehicleAddress(Address mVehicleAddress) {
		this.mVehicleAddress = mVehicleAddress;
	}

	public MapContainerImpl(OMapActivity activity, AMap mapView, OMapLongPressListener touchListener) {
		mMapActivity = activity;
		mMapView = mapView;
		mapViewHelper = MapViewHelper.getInstance();
		oroute = new MapRoute(mMapActivity, mMapView);
		mapLocation = new MapLocation(mMapActivity, mMapView);
		mapLocation.setMapRoute(oroute);
		mapSearch = new MapSearch(mMapActivity, mMapView);

		AMapLongPressHandler longPressHandler = new AMapLongPressHandler(touchListener);
		mapView.setOnMapLongClickListener(longPressHandler);
	}

	@Override
	public void initMapView(int mapLevel, String cityName) {
		this.initMapView(mapLevel);
		if (cityName != null) {
			getCoderCity(cityName);

		}
	}

	@Override
	public void initMapView(int mapLevel, OGeoPoint center) {
		if (center != null) {
			mapViewHelper.setMapCenter(mMapView, center.getAMapPt(), mapLevel);
		}
	}

	@Override
	public void initMapView(float mapLevel) {
		mapViewHelper.setZoom(mMapView, mapLevel);
	}

	@Override
	public void setTraffic(boolean enable) {
		mMapView.setTrafficEnabled(enable);
		oroute.setTraffic(enable);
	}

	@Override
	public void searchByName(String key, PoiType poiType, String cityCode, QueryOptions options) {
		mapSearch.searchByName(key, poiType, cityCode, options);
	}

	@Override
	public void searchNearBy(String key, PoiType poiType, String cityCode, QueryOptions options) {
		mapSearch.searchNearBy(key, poiType, cityCode, options);
	}

	@Override
	public long nextPageResult() {
		return mapSearch.getNextPage();
	}

	private LatLonPoint getGeoPoint(double latit, double longit) {
		return MapViewHelper.getInstance().getPointer(latit, longit);
	}

	@Override
	public void zoomToSpan() {
		if (mapLocation.getBoundBox() == null) {
			return;
		}
		mapViewHelper.zoomToSpan(mMapView, mapLocation.getBoundBox());
	}

	@Override
	public long geoCoderGps(double latitude, double longitude) {
		long id = mapSearch.geoCoderGps(latitude, longitude);
		return id;
	}

	@Override
	public OGeoPoint fromPixels(int x, int y) {
		OGeoPoint pt = mapViewHelper.fromPixels(mMapView, x, y);
		return pt;
	}

	@Override
	public void getCoderCity(final String city) {
		BackgroundThread geoCity = new BackgroundThread(mMapActivity, mMapView, city);
		geoCity.geoCodeCity();
	}

	@Override
	public void getCoderCity(final String city, int mapLevel) {
		BackgroundThread chgCity = new BackgroundThread(mMapActivity, mMapView, city);
		chgCity.setMapLevel(mapLevel);
		chgCity.geoCodeCity();
	}

	@Override
	public void clearMapOverlays() {
		mapViewHelper.clearMapOverlays(mMapView);
	}

	@Override
	public void clearLocations() {
		mapLocation.clearLocation();
	}

	@Override
	public void clearRouteOverlay() {
		mapViewHelper.clearRouteOverlay(mMapView, oroute.getRouteOverlay());
		// mapViewHelper.clearMapOverlay(mMapView, oroute.getMyRouteOverlay());
		mapViewHelper.removeView(mMapView, oroute.getStartLayout());
		mapViewHelper.removeView(mMapView, oroute.getEndLayout());
	}

	@Override
	public void clearLayout(View view) {
		mapViewHelper.removeView(mMapView, view);
	}

	public List<PoiItemInfo> getSearchResultList() {
		return mapSearch.getmSearchResultList();
	}

	public int getPoiPageCount() {
		return mapSearch.getPoiPageCount();
	}

	public long caculateRoute(final PoiItemInfo routeStartPoiItemInfo, final PoiItemInfo routeEndPoiItemInfo,
			String hour, String minutes) {

		return oroute.caculateRoute(routeStartPoiItemInfo, routeEndPoiItemInfo, hour, minutes);
	}

	public long caculateRouteByMode(final PoiItemInfo routeStartPoiItemInfo, final PoiItemInfo routeEndPoiItemInfo,
							  String hour, String minutes, int driveMode) {
		oroute.setDriveMode(driveMode);
		return oroute.caculateRoute(routeStartPoiItemInfo, routeEndPoiItemInfo, hour, minutes);
	}

	@Override
	public long caculateTempRoute(final PoiItemInfo routeStartPoiItemInfo, final PoiItemInfo routeEndPoiItemInfo,
			String hour, String minutes) {
		return oroute.caculateTempRoute(routeStartPoiItemInfo, routeEndPoiItemInfo, hour, minutes);
	}

	@Override
	public void showRoute() {
		oroute.showRoute(false);
	}

	public void showTempRoute() {
		oroute.showTempRoute(false);
	}

	@Override
	public void showLocation(final PoiItemInfo poiItemInfo, int resIcon, LocationType locationType) {
		mapLocation.showLocation(poiItemInfo, resIcon, locationType);
	}

	@Override
	public void showLocation(OGeoPoint geoPoint, int resIcon) {
		mapLocation.showLocation(geoPoint, resIcon);
	}

	@Override
	public void showLocation(final LocationType locationType, final PoiItemInfo poiItemInfo) {
		mapLocation.showLocation(locationType, poiItemInfo);
	}
	@Override
	public void showLocation(final LocationType locationType, final PoiItemInfo poiItemInfo,boolean isShowInfoWindow) {
		mapLocation.showLocation(locationType, poiItemInfo,isShowInfoWindow);
	}

	@Override
	public void showInfoWindow(LocationType locationType) {
		mapLocation.showInfoWindow(locationType);		
	}

	@Override
	public void goToPoint(double latit, double longit) {
		MapViewHelper.getInstance().animateTo(mMapView, this.getGeoPoint(latit, longit));
	}

	@Override
	public void addMapViewLayout(View layout, LocationType type) {
		// mMapView.addView(layout, new OMapView.LayoutParams(
		// OMapView.LayoutParams.WRAP_CONTENT,
		// OMapView.LayoutParams.WRAP_CONTENT, (OGeoPointImpl) pt,
		// OMapView.LayoutParams.BOTTOM_CENTER));
		this.mapLocation.setInfoContentView(layout, type);
	}

	@Override
	public void addMapViewLayout(LinearLayout layout, OGeoPoint pt, int x, int y) {
		// mMapView.addView(layout, new OMapView.LayoutParams(
		// OMapView.LayoutParams.WRAP_CONTENT,
		// OMapView.LayoutParams.WRAP_CONTENT, (OGeoPointImpl) pt, x, y,
		// OMapView.LayoutParams.BOTTOM_CENTER));
	}

	@Override
	public void addMapRouteLayout(LinearLayout layout, OGeoPoint pt, int x, int y, boolean isStart) {
		// mMapView.addView(layout, new OMapView.LayoutParams(
		// OMapView.LayoutParams.WRAP_CONTENT,
		// OMapView.LayoutParams.WRAP_CONTENT, (OGeoPointImpl) pt, x, y,
		// OMapView.LayoutParams.BOTTOM_CENTER));
		// if (isStart) {
		// oroute.setStartLayout(layout);
		// }else{
		// oroute.setEndLayout(layout);
		// }
	}

	@Override
	public List<DriveSegmentInfo> getDriveSegmentResultList() {
		return oroute.getmDriveSegmentResultList();
	}

	@Override
	public String getRouteDistance() {
		return oroute.getRouteDistance();
	}

	@Override
	public String getRouteTime() {
		return oroute.getRouteTime();
	}

	public void setmMapView(AMap mMapView) {
		this.mMapView = mMapView;
	}

	@Override
	public void zoomTo(int mapLevel, double lat, double lon) {
		LatLonPoint center = getGeoPoint(lat, lon);
		MapViewHelper.getInstance().setMapCenter(mMapView, center, mapLevel);
	}

	@Override
	public void setLanguage(Language lan) {
		this.language = lan;
		this.oroute.setLang(language);
	}

	@Override
	public void registerMapRouteListener(ORouteHandlerListener listener) {
		this.mapLocation.registerMapRouteListener(listener);
		this.oroute.registerListener(listener);
	}

	@Override
	public void registerMapSearchListener(OSearchHandlerListener listener) {
		this.mapSearch.registerSearchListener(listener);
	}

	public void removeAllListeners() {
		this.mapSearch.removeListener();
		this.mapLocation.removeListener();
	}

	@Override
	public void clearTempRoutePoints() {
		this.mapLocation.clearTempRoutePoints();
	}

	@Override
	public void removeMapView(View view) {
		MapViewHelper.getInstance().removeView(mMapView, view);
	}

	@Override
	public OGeoPoint getRouteStart() {
		return oroute.getStartLoc();
	}

	@Override
	public OGeoPoint getRouteEnd() {
		return oroute.getEndLoc();
	}

	@Override
	public void showRoute(boolean drawDefault) {
		oroute.showRoute(drawDefault);

	}

	@Override
	public void showTempRoute(boolean drawDefault) {
		oroute.showTempRoute(drawDefault);
	}

	@Override
	public void setDriveMode(int driveMode) {
		oroute.setDriveMode(driveMode);
	}

	@Override
	public void resetRoutePoints(LocationType locationType) {
		// mapLocation.clickHandler(locationType);
	}

	@Override
	public void setRouteIcons(int startIcon, int endIcon, int wayIcon) {
		this.oroute.setRouteIcons(startIcon, endIcon, wayIcon);

	}

	@Override
	public void enableCompass(boolean enable) {
		mapViewHelper.setCompassEnable(mMapView, enable);

	}

	@Override
	public void setZoomControlsEnabled(boolean enable) {
		mapViewHelper.setZoomControlsEnabled(mMapView, enable);
	}
}
